#pragma once
#include <IntelPresentMon/PresentMonAPI2/PresentMonAPI.h>
#include "BlobContainer.h"
#include "ProcessTracker.h"
#include <span>

namespace pmapi
{
    // DynamicQuery specifies what data (metrics) should be gathered and processed every time this query is polled
    // it must be first registered with the API, and then can be queried when given a ProcessTracker to use
    // NOTE: do not create directly; Session is the factory for DynamicQuery
    class DynamicQuery
    {
        friend class Session;
    public:
        // create empty query
        DynamicQuery() = default;
        // free resources
        ~DynamicQuery();
        // move ctor
        DynamicQuery(DynamicQuery&& other) noexcept;
        // move assign
        DynamicQuery& operator=(DynamicQuery&& rhs) noexcept;
        // get size in bytes necessary for a blob to hold data generated by polling this query
        size_t GetBlobSize() const;
        // poll the specified process using this query
        // polling processes frame event data and generates metrics for the time point at which this query was polled
        // makes use of a blob container to manage the output data
        // if the target process has multiple swap chains, will poll data for as many swaps has the container has room for
        void Poll(const ProcessTracker& tracker, BlobContainer& blobs) const;
        // poll the specified process using this query
        // polling processes frame event data and generates metrics for the time point at which this query was polled
        // numSwapChains: input indicates to API how many blobs available, output indicates how many were written
        // if the target process has multiple swap chains, will poll data for as many swaps as there are blobs available
        void Poll(const ProcessTracker& tracker, uint8_t* pBlob, uint32_t& numSwapChains) const;
        // create a blob container sized suited for this query
        // nBlobs parameter will control how many swaps can be polled maximum using the container
        BlobContainer MakeBlobContainer(uint32_t nBlobs) const;
        // clear out this query freeing resources
        void Reset();
        // check if empty
        bool Empty() const;
        // aliases Empty()
        operator bool() const;
    private:
        // function
        DynamicQuery(PM_SESSION_HANDLE hSession, std::span<PM_QUERY_ELEMENT> elements, double winSizeMs, double metricOffsetMs);
        // zero out members, useful after emptying via move or reset
        void Clear_() noexcept;
        // data
        PM_DYNAMIC_QUERY_HANDLE hQuery_ = nullptr;
        size_t blobSize_ = 0ull;
    };
}
